#ifndef STLMODEL_H
#define STLMODEL_H


#include <QObject>
#include <string>
#include "trans.h"
#include <QMutex>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLExtraFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLWidget>
#define GLUT_DISABLE_ATEXIT_HACK
#include <stdio.h>
#include <stdlib.h>

extern class GLUquadric;
using namespace  std;
typedef struct _T_Vertex{
    float x;
    float y;
    float z;
}Vertex;
typedef struct _T_TriAnlge{
    Vertex v1;
    Vertex v2;
    Vertex v3;
}TriAnlge;

typedef std::vector<TriAnlge> TriAngleModel;

class Stlmodel : public QObject
{
    Q_OBJECT
public:
    explicit Stlmodel(QObject *parent = nullptr);
    explicit Stlmodel(QString filePath);

    ~Stlmodel();
    int ShowStlModelVBO();
    int ReadStlFile(FILE* pFile);
    int ShowStlModel(float x,float y,float z);
    void Rotate(float anglex,float angley,float anglez);
    void MoveToOriginCordinary(float x,float y,float z);
    void Move(float x,float y,float z);
    void RotateAxis(float theta);
    void RotateWithLine(float theta,float ax,float ay,float az);
    void Transform(Matrix44f);
    void TransformVBO(Matrix44f);
    uint32_t VertrexSize();
    uint32_t TriangleSize();
    void _setMaxAndMin(float x,float y,float z);
    float *VertrexBuffer();
    void SetView();
    float YSize();
    void SetPosition(float x,float y,float z);
    void SetDHPara(double a,double d,double alpha,double theta);
    Matrix44f DhTransform();
    Matrix44f ATransform();
    void SetPrevModel(Stlmodel *prev);
    void SetNextModel(Stlmodel *next);
    void SetTheta(float);
    void SetThetaRadian(float);
    Matrix44f StackTransform();

    double Theta();
    double Distance();
    double Twist();
    double PosX();
    double PosY();
    double PosZ();
    float *NormalBuffer();
signals:
protected:
    virtual void initializeGL();
private:

    GLUquadric *mQuadric;
    Stlmodel *mNextModel;
    Stlmodel *mPrevModel;
    Matrix44f mStackTransform;
    GLuint mVBO, mVAO, mEBO;
    void setMinMax(float x,float y,float z);
    QOpenGLShaderProgram mShaderProgram;
    GLuint programId;
    bool bLoaded;
    float *mVertix;
    float *mNorm;
    QMutex mMux;
    uint32_t mTriangleCnt;
    uint32_t mVertexCnt;

    // box model
    float mMinx;
    float mMaxx;
    float mMiny;
    float mMaxy;
    float mMinz;
    float mMaxz;

    //cordinate origin position at global cordinate
    float mXPos;
    float mYPos;
    float mZPos;

    // DH parameter
    double mTwist;
    double mDistance;
    double mTheta;
    double mAlpha;
    // PrevDH para for caculate axis
    double mPrevTwist;
    double mPrevDistance;
    double mPrevTheta;
    double mPrevAlpha;
    double mOffsetX;
    double mOffsetY;
    double mOffsetZ;

    void multMatrixf(Matrix44f );
    bool readASCII(const char * buffer);
    bool readBinary(const char *buffer);
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

#endif // STLMODEL_H
